package com.example.demo.itemReader.ReaderRestart;


import org.springframework.batch.item.*;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;

@Component("restartDemoReader")
public class RestartReader implements ItemStreamReader<Customer> {
    private FlatFileItemReader<Customer> reader = new FlatFileItemReader<Customer>();
    private long curLine = 0;
    private boolean restart = false;
    private ExecutionContext executionContext;
    public   RestartReader(){
        reader.setResource(new ClassPathResource("customerRestart.txt"));
        //reader.setLinesToSkip(1);//跳过第一行这里没用 因为这个程序read是根据curLine来的 这里跳过了 运行的时候其实没跳过

        //解析数据
        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
        tokenizer.setNames(new String[]{"id","firstName","lastName","birthday"});
        //把解析出的一行数据映射为customer对象
        DefaultLineMapper<Customer> mapper = new DefaultLineMapper<>();
        mapper.setLineTokenizer(tokenizer);
        mapper.setFieldSetMapper(new FieldSetMapper<Customer>() {
            @Override
            public Customer mapFieldSet(FieldSet fieldSet) throws BindException {
                Customer customer = new Customer();
                customer.setId(fieldSet.readLong("id"));
                customer.setFirstName(fieldSet.readString("firstName"));
                customer.setLastName(fieldSet.readString("lastName"));
                customer.setBirthday(fieldSet.readString("birthday"));
                return customer;
            }
        });
        mapper.afterPropertiesSet();
        reader.setLineMapper(mapper);

    }

    @Override
    public Customer read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        Customer customer = null;
        this.curLine ++;
        if(restart){
            reader.setLinesToSkip(Long.valueOf(this.curLine).intValue()-1);
            restart = false;
            System.out.println("Start reading from line "+ this.curLine);
        }
        reader.open(this.executionContext);
        customer = reader.read();
        //认为给个异常 当读到FirstName=="WrongName"是抛出异常 此时不再update  修改文件内容后再次运行程序由于curLine被存入数据库
        //再次开始会从抛出异常所在的chunk读取数据
        if(customer!=null&&customer.getFirstName().equals("WrongName")){
            throw new RuntimeException("Something wrong .Customer id"+customer.getId());
        }
        return customer;
    }
    //open在每个step之前执行
    @Override
    public void open(ExecutionContext executionContext) throws ItemStreamException {
        this.executionContext = executionContext;
        if(executionContext.containsKey("curLine")){
            this.curLine = executionContext.getLong("curLine");
            this.restart = true;
        }
        else {
            this.curLine = 0;
            executionContext.put("curLine",this.curLine);
            System.out.println("Start reading from line"+this.curLine+1);
        }

    }
    //update在每个chunk之前执行
    @Override
    public void update(ExecutionContext executionContext) throws ItemStreamException {
        executionContext.put("curLine",this.curLine);
        System.out.println("currentLine"+this.curLine);

    }
    //close在每个step之后执行
    @Override
    public void close() throws ItemStreamException {

    }
}
